#pragma once

#include <iostream>
#include <vector>
#include <sys/epoll.h>
#include "Log.hpp"
#include "Connection.hpp"
#include "Epoller.hpp"
#include "Common.hpp"
#include <unistd.h>
#include <unordered_map>
#include <memory>
#include <cstdio>
#include <cstdlib>
#include <ctime>

const int recv_num = 128;

class Reactor
{
private:
    bool IsConnectionExistHelper(int sockfd)
    {
        auto iter = _connection.find(sockfd);
        if (iter == _connection.end())
            return false;
        return true;
    }
    bool IsConnectionExist(int sockfd)
    {
        return IsConnectionExistHelper(sockfd);
    }
    bool IsConnectionExist(const std::shared_ptr<Connection> &Con)
    {
        return IsConnectionExistHelper(Con->GetSockfd());
    }

    bool IsConnectionEmpty()
    {
        return _connection.empty();
    }
    int LoopOnce(int timeout)
    {
        return _epoller_ptr->WaitEvents(_recv, recv_num, timeout);
    }

    // 事件派发器
    void Dispacter(int n)
    {
        for (int i = 0; i < n; i++)
        {
            int sockfd = _recv[i].data.fd;
            uint32_t event = _recv[i].events;

            if (_is_taskthread)
            {
                // epoll中各种错误全部统一归为IO错误
                // 由Expector统一处理
                if (event & EPOLLERR||event & EPOLLHUP)
                    event |= (EPOLLIN | EPOLLOUT);

                if (event & EPOLLIN)
                {
                    if (IsConnectionExist(sockfd))
                        _connection[sockfd]->Recver();
                }

                if (event & EPOLLOUT)
                {
                    if (IsConnectionExist(sockfd))
                        _connection[sockfd]->Sender();
                }
            }
            else
            {
                //listensockfd就绪
                if (event & EPOLLERR||event & EPOLLHUP)
                    event |= (EPOLLIN | EPOLLOUT);
                if (event & EPOLLIN)
                {
                    if (IsConnectionExist(sockfd))
                    {
                        _connection[sockfd]->Recver();
                        //简单负载均衡 分配给子线程
                        int t = rand()%_efds.size();

                        uint64_t value = 1; 
                        ssize_t n = write(_efds[t], &value, sizeof(value));
                    }   
                }
            }
        }
    }

public:
    Reactor(bool is_taskthread = false) : _epoller_ptr(std::make_unique<Epoller>()), _is_running(false), _is_taskthread(is_taskthread)
    {
    }

    void Loop()
    {
        // 如果管理缓冲区_connection为空则不启动服务
        if (IsConnectionEmpty())
            return;
        _is_running = true;
        int timeout = 5000;
        while (_is_running)
        {
            // DEBUG打印合法fd
            if(_is_taskthread)
                PrintSockfd();   
            else
                Printefds();
            // 每轮询一次，派发一次
            int n = LoopOnce(timeout);
            Dispacter(n);
        }
        _is_running = false;
    }

    // 添加链接
    void AddConnection(std::shared_ptr<Connection> &Con)
    {
        if (IsConnectionExist(Con))
        {
            LOG(Loglevel::WARN) << "connection is exist: " << Con->GetSockfd();
            return;
        }
        // 将Con对应的fd以及关心的事件写入到内核中
        int events = Con->GetEvent();
        int sockfd = Con->GetSockfd();
        _epoller_ptr->AddEvent(sockfd, events);

        // 设置回指指针
        Con->SetOwner(this);

        // 设置到map中统一管理
        _connection[sockfd] = Con;
    }

    // 修改相关事件的读写状态
    void EnableReadWrite(int sockfd, bool r, bool w)
    {
        // 不存在的无法修改
        if (!IsConnectionExist(sockfd))
        {
            LOG(Loglevel::ERROR) << "sockfd is not exit: " << sockfd;
            return;
        }
        uint32_t new_event = (EPOLLET | (r ? EPOLLIN : 0) | (w ? EPOLLOUT : 0));
        _connection[sockfd]->SetEvent(new_event);

        // 写透到内核中
        _epoller_ptr->ModEvent(sockfd, new_event);
    }

    // 删除链接
    void DelConnection(int sockfd)
    {
        _epoller_ptr->DelEvent(sockfd);
        _connection.erase(sockfd);
        close(sockfd);
    }
    
    void AddEfd(int efd)
    {
        _efds.push_back(efd);
    }

    void Stop()
    {
        _is_running = false;
    }

    ~Reactor()
    {
        while(!_efds.empty())
        {
            close(_efds.back());
            _efds.pop_back();
        }
    }

    //DEBUG
    void PrintSockfd()
    {
        std::cout << "合法的sockfd: ";
        for (auto &Con : _connection)
            std::cout << Con.second->GetSockfd() << " ";
        std::cout << "\r\n";
    }

    void Printefds()
    {
        std::cout << "合法的efds: ";
        for (auto &efd : _efds)
            std::cout << efd << " ";
        std::cout << "\r\n";
    }

private:
    // epoll模型
    std::unique_ptr<Epoller> _epoller_ptr;

    // 服务器状态
    bool _is_running;
    //是否为子线程
    bool _is_taskthread; 

    // 管理对应的fd
    std::unordered_map<int, std::shared_ptr<Connection>> _connection;

    // 管理efd
    std::vector<int> _efds;

    // 一次读取的事件
    struct epoll_event _recv[recv_num];
};
